﻿using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.IO;
using System.Runtime.InteropServices;
using System.Windows.Forms;
using StockLib.Data;
using System.Threading;
using System.ComponentModel;

namespace StockLib.Quote
{
    public class ReceiverDataEventArgs : EventArgs
    {
        private DataType _dataType = DataType.Unknown;

        private KType _kType = KType.None;

        private object _data = null;


        public ReceiverDataEventArgs()
            : this(DataType.Unknown)
        {
        }

        public ReceiverDataEventArgs(DataType dataType)
            : this(dataType, null)
        {
        }

        public ReceiverDataEventArgs(DataType dataType, object data)
            : this(dataType, data, KType.None)
        {
        }

        public ReceiverDataEventArgs(DataType dataType, object data, KType kType)
        {
            this._dataType = dataType;
            this._data = data;
            this._kType = kType;
        }

        public DataType DataType
        {
            get { return this._dataType; }
            set { this._dataType = value; }
        }

        public KType KType
        {
            get { return this._kType; }
            set { this._kType = value; }
        }

        public object Data
        {
            get { return this._data; }
            set { this._data = value; }
        }
    }

    public class ReceiverStatusEventArgs : EventArgs
    {
        private bool _isWorking;

        public bool IsWorking
        {
            get
            {
                return this._isWorking;
            }
        }

        public ReceiverStatusEventArgs(bool isWorking) : base()
        {
            this._isWorking = isWorking;
        }
    }

    public delegate void ReceiverDataEventHandler(object sender, ReceiverDataEventArgs e);

    public delegate void ReceiverStatusEventHandler(object sender, ReceiverStatusEventArgs e);

    public partial class StockReceiver
    {
        #region 接收数据类型
        public const int RCV_REPORT = 0x3f001234;           // 接收行情数据
        public const int RCV_FILEDATA = 0x3f001235;         // 接收文件数据
        public const int RCV_FENBIDATA = 0x3f001301;        // 接收分笔数据
        #endregion

        #region 接收文件类型
        public const int FILE_HISTORY_EX = 2;               // 补日线文件
        public const int FILE_MINUTE_EX = 4;                // 补分钟线文件
        public const int FILE_POWER_EX = 6;                 // 补充除权文件
        public const int FILE_5MINUTE_EX = 81;              // 补5分钟线文件
        public const int FILE_BASE_EX = 0x1000;             // 补基本资料文件
        public const int FILE_NEWS_EX = 0x1002;             // 补新闻类文件
        public const int FILE_HTML_EX = 0x1004;             // 补HTML文件
        #endregion

        #region 接收文件数据包头
        public const UInt32 EKE_HEAD_TAG = 0xffffffff;      //数据头结构标记
        #endregion

        public const int MARKET_SH = 0X4853;
        public const int MARKET_SZ = 0X5A53;

        /// <summary>
        /// 接收数据事件
        /// </summary>
        public event ReceiverDataEventHandler DataChanged;

        /// <summary>
        /// 状态更改事件
        /// </summary>
        public event ReceiverStatusEventHandler StatusChanged;

        /// <summary>
        /// 接收数据的窗口
        /// </summary>
        private Form _form = null;

        /// <summary>
        /// 引擎是否在工作
        /// </summary>
        private bool _working = false;

        /// <summary>
        /// 单例实例
        /// </summary>
        private static StockReceiver _instance = new StockReceiver();

        /// <summary>
        /// 构造函数
        /// </summary>
        private StockReceiver()
        {
        }

        /// <summary>
        /// 创建接收器窗口
        /// </summary>
        /// <returns></returns>
        public void CreateWindow()
        {
            if (_form == null)
            {
                _form = new StockReceiverForm();
            }
        }

        /// <summary>
        /// 销毁接收器窗口
        /// </summary>
        /// <returns></returns>
        public void DestroyWindow()
        {
            if (_form != null)
            {
                _form.Close();
                _form.Dispose();
            }
        }

        /// <summary>
        /// 访问单例
        /// </summary>
        /// <returns></returns>
        public static StockReceiver Instance
        {
            get
            {
                return _instance;
            }
        }

        public bool IsWorking
        {
            get { return this._working; }
        }

        public bool StartWorking()
        {
            if (_form == null)
                return false;

            if (!_working)
            {
                if (StockReceiverDriver.LoadDriver() && StockReceiverDriver.Init(_form.Handle))
                {
                    _working = true;
                    OnStatusChanged(this, new ReceiverStatusEventArgs(_working));
                }
            }

            return _working;
        }

        public bool StopWorking()
        {
            if (_form == null)
                return false;

            if (_working)
            {
                StockReceiverDriver.Quit(_form.Handle);
                StockReceiverDriver.UnloadDriver();
                _working = false;
                OnStatusChanged(this, new ReceiverStatusEventArgs(_working));
            }

            return !_working;
        }

        /// <summary>
        /// 根据消息结构，对接收到的数据进行分析
        /// </summary>
        /// <param name="m">消息结构</param>
        public void OnReceiveData(ref Message m)
        {
            ReceiveData tsdata = (ReceiveData)Marshal.PtrToStructure(m.LParam, typeof(ReceiveData));

            switch ((int)m.WParam)
            {
                case RCV_REPORT:    //行情数据
                    ReceiveReport(ref tsdata);
                    break;

                case RCV_FENBIDATA: //分笔数据
                    ReceiveFileTick(ref tsdata);
                    break;

                case RCV_FILEDATA:  //文件数据
                    switch (tsdata.m_wDataType)
                    {
                        case FILE_HISTORY_EX:   // 日线
                            ReceiveFileHistory(ref tsdata, KType.Day);
                            break;

                        case FILE_5MINUTE_EX:   // 5分钟
                            ReceiveFileHistory(ref tsdata, KType.Min5);
                            break;

                        case FILE_MINUTE_EX:    // 分时
                            ReceiveFileMinute(ref tsdata);
                            break;

                        case FILE_POWER_EX:     // 除权
                            ReceiveFilePower(ref tsdata);
                            break;

                        case FILE_BASE_EX:      // 基本资料
                            ReceiveFileBase(ref tsdata);
                            break;

                        case FILE_NEWS_EX:      // 新闻
                            ReceiveFileNews(ref tsdata);
                            break;

                        case FILE_HTML_EX:      // HTML文件
                            break;
                    }

                    break;
            }
        }

        public static StockMarket ConvertMarketToInternal(UInt16 wMarket)
        {
            switch (wMarket)
            {
                case MARKET_SH:
                    return StockMarket.SHSE;

                case MARKET_SZ:
                    return StockMarket.SZSE;
            }

            return StockMarket.Unknown;
        }

        protected void OnDataChanged(object sender, ReceiverDataEventArgs e)
        {
            if (DataChanged != null)
            {
                DataChanged(sender, e);
            }
        }

        protected void OnStatusChanged(object sender, ReceiverStatusEventArgs e)
        {
            if (StatusChanged != null)
            {
                StatusChanged(sender, e);
            }
        }

        class StockReceiverForm : Form
        {
            private const int RCV_DATA_MSG = 0x8001;            // 指定使用的消息

            protected override CreateParams CreateParams
            {
                get
                {
                    CreateParams cp = base.CreateParams;
                    cp.Height = 0;
                    cp.Width = 0;
                    cp.Style |= 0x40000000;
                    cp.ExStyle |= 0x08000000;
                    cp.ClassStyle |= 0x0200;
                    return cp;
                }
            }

            //重载缺省窗口过程，捕获数据接收事件，然后进行数据处理
            //数据处理时，将触发数据更新事件
            protected override void DefWndProc(ref Message msg)
            {
                switch (msg.Msg)
                {
                    case RCV_DATA_MSG:
                        StockReceiver.Instance.OnReceiveData(ref msg);
                        return;
                }

                base.DefWndProc(ref msg);
            }
        }
    }
}
